ページ離脱防止機能を実装する | 您所在的位置:网站首页 › onbeforeunload safari › ページ離脱防止機能を実装する |
beforeunloadイベントを利用して実装
先日、とあるCMSの管理画面にて、記事入力途中・画像入力途中でのページ離脱防止機能の実装を行いました。 要件としては、Google Chromeのみで、離脱時にアラートを表示するというものでした。 ページ遷移前に発火するbeforeunloadというイベントを利用した実装を行なったのですが、僕自身このイベントに真正面から向かい合って実装に取り組んだことがなかったので、ところどころ小さな落とし穴があったため、その備忘録としてこの記事を書かせていただきます。 ちなみに、beforeunloadイベントの詳細はこちらを参照ください。 developer.mozilla.org テストは必ず入力フィールドのあるページでとても基本的な落とし穴ですがテストは必ず入力フィールドのあるページで行なってください。 Google Chrome公式でもRequire user gesture for beforeunload dialogsと記載されています。 文字入力や画面になんらかのアクションがないと、離脱防止は動きません。開いて何もせずに「戻る」を押してしまうと、何も起きずに離脱してしまいます。https://donow.jp/skillup/?p=3271 www.chromestatus.com 僕はこれに気づかず、入力フィールドのないページでなんどもブラウザバックボタンを押しては、何も起こらないことに首をひねってしまいました。 window.onbeforeunloadイベントプロパティに関数を登録イベントハンドリングにはaddEventListenerメソッドやonメソッド(jQuery)などの方法がありますが、後述する理由によりwindow.onbeforeunloadイベントプロパティに関数を登録する方法を採用しています。 Chromeとそれ以外のブラウザとで若干方法が異なりますが、必ずreturnをするかe.returnValueを指定してください。 同時に指定することも可能ですが、とにかくreturnをしないと離脱防止は動きません。 window.onbeforeunload = function(e){ return "このページを離れますか?"; // Google Chrome以外 e.returnValue = "このページを離れますか?"; // Google Chrome }また、Google Chromeのみ、カスタムメッセージ(つまりreturnValueやreturnに渡している文字列)は設定できず、ブラウザデフォルトのメッセージしか表示ができない仕様になっているそうです。 この件についてはこちらの記事をご参照ください。 qiita.com フォームのsubmit時は無効にするbeforeunloadイベントはすべてのページ遷移時に発火するので、当然ながらフォームのsubmit時も発火します。 ユーザビリティのため、フォームのsubmit時は無効にするのが好ましいでしょう。 方法としてはフォームのsubmit時にbeforeunloadイベントとそれに対応する関数との紐づけを削除するのですが、removeEventListenerメソッドでもoffメソッド(jQuery)でもその紐づけを切ることができませんでした。 そこで、window.onbeforeunloadプロパティにnullを代入することで対応しました。 $('form').on('submit', function(e){ e.preventDefault(); window.onbeforeunload = null; // 関数を削除 var $this = $(this); var isPassed = confirm('記事を登録しますか?'); if (isPassed) $this.submit(); });記事の登録時には確認ダイアログを表示してほしいとの要件であったため、このような実装になっています。 これらをまとめると、以下のようになります。 window.onbeforeunload = function(e){ return "このページを離れますか?"; // Google Chrome以外 e.returnValue = "このページを離れますか?"; // Google Chrome } $('form').on('submit', function(e){ e.preventDefault(); window.onbeforeunload = null; // 関数を削除 var $this = $(this); var isPassed = confirm('記事を登録しますか?'); if (isPassed) $this.submit(); }); |
CopyRight 2018-2019 实验室设备网 版权所有 |